#include "NuevoProceso.h"

#include <gtkmm/menuitem.h>
#include <unistd.h>
#include <sys/wait.h>


NuevoProceso::NuevoProceso(Glib::RefPtr<Gtk::Builder> b, std::string nomMenu, std::string nomProg){
	// Obtiene una referencia al menu
	Gtk::MenuItem* mi = 0;
	b->get_widget(nomMenu, mi);
	if (!mi) throw std::runtime_error("Error, no se encontró '"+ nomMenu);

	// Conecta una señal
	mi->signal_activate().connect( sigc::mem_fun(*this, &NuevoProceso::abrirPrograma) );

	// Guarda el nombre del programa a ejecutar
	this->_nombrePrograma = nomProg;
}


NuevoProceso::~NuevoProceso(){
}


// Esta forma de generar procesos salio de
// http://stackoverflow.com/questions/2422068/how-can-i-run-an-external-program-without-waiting-for-it-to-exit/2422080#2422080
void NuevoProceso::abrirPrograma(){
	// Se crea un nuevo proceso hijo
	int fork_rv = fork();
	if (fork_rv == 0){

		// Se crea un proceso nieto
		fork_rv = fork();
		if (fork_rv == 0){
			// El nieto ejecuta el proceso señalado
			execl(this->_nombrePrograma.c_str(), this->_nombrePrograma.c_str(), 0);
			_exit(1);

		} else if (fork_rv == -1){
			throw std::runtime_error("Error al parir el nuevo proceso nieto");
		}

		// Todo salio bien
		_exit(0);

	} else if (fork_rv != -1){
		// El padre espera al proceso hijo (deberia salir rapido)
		int status;
		waitpid(fork_rv, &status, 0);

	} else if (fork_rv == -1){
		throw std::runtime_error("Error al parir el nuevo proceso hijo");
	}
}



